// @Date         2021-11-29
// @Author       Aaron Zhang
// @Description
// @FileName      middleware.go

package command

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/AlecAivazis/survey/v2"
	"github.com/go-git/go-git/v5"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"zin/framework/cobra"
	"zin/framework/command/template"
	"zin/framework/util"
)

func initMiddlewareCommand() *cobra.Command {
	middlewareCommand.AddCommand(middlewareListCommand, middlewareMigrateCommand, middlewareCreateCommand)
	return middlewareCommand
}

var middlewareCommand = &cobra.Command{
	Use:   "middleware",
	Short: "中间件相关操作",
	RunE: func(cmd *cobra.Command, args []string) error {
		cmd.Help()
		return nil
	},
}
var middlewareListCommand = &cobra.Command{
	Use:   "list",
	Short: "列出所有中间件",
	RunE: func(cmd *cobra.Command, args []string) error {
		middlewarePath := path.Join(util.GetAppProvider().MiddlewareFolder())
		util.CheckDirExistsAndMk(middlewarePath)

		// 读取文件夹
		files, err := ioutil.ReadDir(middlewarePath)
		if err != nil {
			return err
		}

		for _, f := range files {
			if f.IsDir() {
				fmt.Println(f.Name())
			}
		}
		return nil

	},
}

// 从gin-contrib中迁移中间件
var middlewareMigrateCommand = &cobra.Command{
	Use:   "migrate",
	Short: "迁移gin-contrib中间件, 迁移地址：https://github.com/gin-contrib/[middleware].git",
	RunE: func(c *cobra.Command, args []string) error {
		fmt.Println("迁移一个Gin中间件")
		var repo string

		{
			prompt := &survey.Input{
				Message: "请输入中间件名称：",
			}
			err := survey.AskOne(prompt, &repo)
			if err != nil {
				return err
			}
		}

		// step2 : 下载git到一个目录中
		middlewarePath := util.GetAppProvider().MiddlewareFolder()
		fInfo, _ := os.Stat(filepath.Join(util.GetAppProvider().MiddlewareFolder(), name))
		if fInfo != nil {
			return errors.New("中间件目录已经存在")
		}
		util.CheckDirExistsAndMk(middlewarePath)

		url := "https://github.com/gin-contrib/" + repo + ".git"
		fmt.Println("下载中间件 gin-contrib:")
		fmt.Println(url)

		_, err := git.PlainClone(path.Join(middlewarePath, repo), false, &git.CloneOptions{
			URL:      url,
			Progress: os.Stdout,
		})

		if err != nil {
			return err
		}

		// step3:删除不必要的文件
		repoFolder := path.Join(middlewarePath, repo)
		needDelFile := []string{
			"go.mod",
			"go.sum",
			".git",
			".gitignore",
			"LICENSE",
			"README.md",
		}

		for _, v := range needDelFile {
			fmt.Println("remove " + path.Join(repoFolder, v))
			os.Remove(path.Join(repoFolder, v))
		}

		// step4 : 替换关键词
		filepath.Walk(repoFolder, func(path string, info os.FileInfo, err error) error {
			if info.IsDir() {
				return nil
			}

			if filepath.Ext(path) != ".go" {
				return nil
			}

			c, cErr := ioutil.ReadFile(path)
			if cErr != nil {
				return cErr
			}
			isContain := bytes.Contains(c, []byte("github.com/gin-gonic/gin"))
			if isContain {
				fmt.Println("更新文件:" + path)
				c = bytes.ReplaceAll(c, []byte("github.com/gin-gonic/gin"), []byte("zin/framework/gin"))
				err = ioutil.WriteFile(path, c, os.ModePerm)

				if err != nil {
					return err
				}
			}

			return nil
		})

		return nil
	},
}

// providerCreateCommand 创建一个新的服务，包括服务提供者，服务接口协议，服务实例
var middlewareCreateCommand = &cobra.Command{
	Use:     "new",
	Aliases: []string{"create", "init"},
	Short:   "创建一个中间件",
	RunE: func(c *cobra.Command, args []string) error {
		middlewarePath := util.GetAppProvider().MiddlewareFolder()
		fmt.Println("创建一个中间件")

		var name string
		var folder string

		{
			prompt := &survey.Input{
				Message: "请输入中间件名称：",
			}
			err := survey.AskOne(prompt, &name)
			if err != nil {
				return err
			}
		}

		{
			prompt := &survey.Input{
				Message: "请输入中间件所在目录名称(默认: 同中间件名称):",
			}
			err := survey.AskOne(prompt, &folder)
			if err != nil {
				return err
			}
		}

		if folder == "" {
			folder = name
		}

		util.CheckDirExistsAndMk(middlewarePath)
		fInfo, _ := os.Stat(filepath.Join(middlewarePath, folder, name+".go"))
		if fInfo != nil {
			return errors.New("中间件目录已经存在")
		}

		// 开始创建文件
		data := map[string]interface{}{
			"name": name,
		}
		err := template.CreateNewMiddleware(name, data)
		if err != nil {
			return err
		}
		fmt.Println("创建中间件成功, 文件夹地址:", filepath.Join(util.GetAppProvider().MiddlewareFolder(), folder))
		return nil
	},
}
